package com.insigma.business.qrcode.soldier.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.Feature;

import com.insigma.business.qrcode.soldier.dto.StatsDataTypeEnum;
import com.insigma.business.qrcode.soldier.entity.DataScreenStatisticsDO;
import com.insigma.business.qrcode.soldier.request.SoldierStatsRequest;
import com.insigma.business.qrcode.soldier.service.DataScreenStatisticsService;
import com.insigma.business.qrcode.soldier.service.SoldierDataStatsService;
import com.insigma.business.qrcode.soldier.util.ThreadPoolManager;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.util.Strings;
import org.slf4j.MDC;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.UUID;


@Slf4j
@Component
public class SoldierDataBuffer {

    @Autowired
    private DataScreenStatisticsService dataScreenStatisticsService;

    public <T> T querySoldierDate(SoldierStatsRequest soldierStatsRequest, StatsDataTypeEnum statsDataTypeEnum, Class<T> clazz, SoldierDataStatsService<T> service) {
        String adminAreaCode = soldierStatsRequest.getAdminAreaCode();

        if (adminAreaCode.startsWith("330110011")) {
            DataScreenStatisticsDO stats = dataScreenStatisticsService.getLastOneByAreaCode(adminAreaCode,
                    statsDataTypeEnum.name());
            if (stats != null) {
                return JSONObject.parseObject(stats.getData(), clazz, Feature.OrderedField);
            }
        }

        DataScreenStatisticsDO stats = dataScreenStatisticsService.getLastByAreaCode(adminAreaCode, statsDataTypeEnum.name());
        log.error("mainScreen:stat{}", stats);

        T t = null;
        if (stats != null) {
            log.error("mainScreen:{}", 1);
            t = JSONObject.parseObject(stats.getData(), clazz, Feature.OrderedField);
            if (System.currentTimeMillis() - stats.getCreateDatetime().getTime() > statsDataTypeEnum.getExpireTime()) {
                log.error("mainScreen:{}", 2);
                t = service.dynamicStatistics(soldierStatsRequest, t);
                String traceId = MDC.get("traceId");
                ThreadPoolManager.getInstance().submit(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            MDC.put("traceId", Strings.isBlank(traceId) ? UUID.randomUUID().toString() : traceId);
                            T result = service.basicStatistics(soldierStatsRequest);
                            result = service.dynamicStatistics(soldierStatsRequest, result);
                            insertSoldierBasicDO(adminAreaCode, result, statsDataTypeEnum);
                            log.error("mainScreen:{}", 9);
                        } catch (Exception e) {
                            log.error("e:{}", e);
                        }
                    }
                });

            } else {

                t = service.dynamicStatistics(soldierStatsRequest, t);
                service.mock(soldierStatsRequest, t);
                log.error("mainScreen:{},t= {}", 3, t);
                return t;
            }
        } else {
            log.error("mainScreen:{}", 4);
            t = service.basicStatistics(soldierStatsRequest);
            t = service.dynamicStatistics(soldierStatsRequest, t);
            T finalT = t;
            log.error("mainScreen:{}, t ={}", 5, t);
            ThreadPoolManager.getInstance().submit(new Runnable() {
                @Override
                public void run() {
                    try {
                        insertSoldierBasicDO(adminAreaCode, finalT, statsDataTypeEnum);
                    } catch (Exception e) {
                        log.error("e:{}", e);
                    }
                }
            });
        }
        log.error("mainScreen:{}, t={}", 6, t);
        service.mock(soldierStatsRequest, t);
        log.error("mainScreen:{}, t={}", 7, t);

        return t;
    }

    private <T> void insertSoldierBasicDO(String adminAreaCode, T soldierStatsDTO, StatsDataTypeEnum statsDataTypeEnum) {
        DataScreenStatisticsDO statisticsDO = new DataScreenStatisticsDO();
        statisticsDO.setAdminAreaCode(adminAreaCode);
        statisticsDO.setData(JSON.toJSONString(soldierStatsDTO));
        statisticsDO.setCreateDatetime(new Date());
        statisticsDO.setStatsType(statsDataTypeEnum.name());

        dataScreenStatisticsService.insert(statisticsDO);
    }


}
